`timescale 1ns / 1ps
/**
 ******************************************************************************
 * @file    axi_to_jtag_lm.v
 * @author  KEN
 * @version V1.0
 * @date    Jul. 2nd, 2020
 * @brief   AXI-to-JTAG(Linear Memory)
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; COPYRIGHT 2020 K'sP</center></h2>
 **/

module axi_to_jtag_lm
	   #
	   (
		   parameter integer C_M_JTAG_CLK_FREQUENCY = 100e6,

		   //9 registers, nid 6 bit address
		   parameter integer C_S_AXI_ADDR_WIDTH = 5,
		   parameter integer C_S_AXI_DATA_WIDTH = 32,
		   
		   parameter integer C_JTAG_TYPE = 0, //0=normal, 1=with tri io control
		   parameter integer C_JTAG_TRI_POLARITY = 0, //0=<low as input, high as output> 1=<high as input, low as output>

		   parameter integer C_VECTOR_LEN = 128,
		   
		   parameter integer C_M_AXI_MAX_BURST_LENGTH = 256,
		   parameter integer C_M_AXI_ADDR_WIDTH = 32,
		   parameter integer C_M_AXI_DATA_WIDTH = 64
	   )
	   (
		   /***********************************************************************/
		   //Slave AXI4-Lite interface
		   /***********************************************************************/
		   //Global ACLK
		   (* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 s_axi_lite_aclk CLK" *)
		   (* X_INTERFACE_PARAMETER = "ASSOCIATED_BUSIF s_axi_lite, ASSOCIATED_RESET s_axi_lite_aresetn" *)
		   input wire s_axi_lite_aclk,

		   //Global ARESETn
		   (* X_INTERFACE_INFO = "xilinx.com:signal:reset:1.0 s_axi_lite_aresetn RST" *)
		   (* X_INTERFACE_PARAMETER = "POLARITY ACTIVE_LOW" *)
		   input wire s_axi_lite_aresetn,

		   //Write address channel. AWVALID, AWREADY, AWADDR, AWPROT
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite AWVALID" *)
		   input wire s_axi_lite_awvalid,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite AWREADY" *)
		   output wire s_axi_lite_awready,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite AWADDR" *)
		   input [(C_S_AXI_ADDR_WIDTH - 1): 0] s_axi_lite_awaddr,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite AWPROT" *)
		   input [2: 0] s_axi_lite_awprot,

		   //Write data channel. WVALID, WREADY, WDATA, WSTRB
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite WVALID" *)
		   input wire s_axi_lite_wvalid,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite WREADY" *)
		   output wire s_axi_lite_wready,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite WDATA" *)
		   input wire [(C_S_AXI_DATA_WIDTH - 1): 0] s_axi_lite_wdata,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite WSTRB" *)
		   input wire [((C_S_AXI_DATA_WIDTH + 7) / 8 - 1): 0] s_axi_lite_wstrb,

		   //Write response channel. BVALID, BREADY, BRESP
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite BVALID" *)
		   output wire s_axi_lite_bvalid,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite BREADY" *)
		   input wire s_axi_lite_bready,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite BRESP" *)
		   output wire [1: 0] s_axi_lite_bresp,

		   //Read address channel. ARVALID, ARREADY, ARADDR, ARPROT
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite ARVALID" *)
		   input wire s_axi_lite_arvalid,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite ARREADY" *)
		   output wire s_axi_lite_arready,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite ARADDR" *)
		   input wire [(C_S_AXI_ADDR_WIDTH - 1): 0] s_axi_lite_araddr,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite ARPROT" *)
		   input wire [2: 0] s_axi_lite_arprot,

		   //Read data channel. RVALID, RREADY, RDATA, RRESP
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite RVALID" *)
		   output wire s_axi_lite_rvalid,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite RREADY" *)
		   input wire s_axi_lite_rready,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite RDATA" *)
		   output wire [(C_S_AXI_DATA_WIDTH - 1): 0] s_axi_lite_rdata,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 s_axi_lite RRESP" *)
		   output wire [1: 0] s_axi_lite_rresp,

		   /***********************************************************************/
		   //Master AXI4 interface
		   /***********************************************************************/
		   //Global ACLK
		   (* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 m_axi_aclk CLK" *)
		   (* X_INTERFACE_PARAMETER = "ASSOCIATED_BUSIF m_axi, ASSOCIATED_RESET m_axi_aresetn" *)
		   input wire m_axi_aclk,

		   //Global ARESETn
		   (* X_INTERFACE_INFO = "xilinx.com:signal:reset:1.0 m_axi_aresetn RST" *)
		   (* X_INTERFACE_PARAMETER = "POLARITY ACTIVE_LOW" *)
		   input wire m_axi_aresetn,

		   //Write address channel.
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi AWADDR" *)
		   output wire [(C_M_AXI_ADDR_WIDTH - 1): 0] m_axi_awaddr,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi AWLEN" *)
		   output wire [7: 0] m_axi_awlen,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi AWSIZE" *)
		   output wire [2: 0] m_axi_awsize,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi AWBURST" *)
		   output wire [1: 0] m_axi_awburst,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi AWLOCK" *)
		   output wire m_axi_awlock,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi AWCACHE" *)
		   output wire [3: 0] m_axi_awcache,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi AWPROT" *)
		   output wire [2: 0] m_axi_awprot,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi AWQOS" *)
		   output wire [3: 0] m_axi_awqos,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi AWVALID" *)
		   output wire m_axi_awvalid,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi AWREADY" *)
		   input wire m_axi_awready,

		   //Write data channel.
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi WDATA" *)
		   output wire [(C_M_AXI_DATA_WIDTH - 1): 0] m_axi_wdata,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi WSTRB" *)
		   output wire [(C_M_AXI_DATA_WIDTH / 8 - 1): 0] m_axi_wstrb,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi WLAST" *)
		   output wire m_axi_wlast,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi WVALID" *)
		   output wire m_axi_wvalid,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi WREADY" *)
		   input wire m_axi_wready,

		   //Write response channel.
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi BRESP" *)
		   input wire [1: 0] m_axi_bresp,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi BVALID" *)
		   input wire m_axi_bvalid,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi BREADY" *)
		   output wire m_axi_bready,

		   //Read address channel.
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi ARADDR" *)
		   output wire [(C_M_AXI_ADDR_WIDTH - 1): 0] m_axi_araddr,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi ARLEN" *)
		   output wire [7: 0] m_axi_arlen,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi ARSIZE" *)
		   output wire [2: 0] m_axi_arsize,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi ARBURST" *)
		   output wire [1: 0] m_axi_arburst,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi ARLOCK" *)
		   output wire m_axi_arlock,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi ARCACHE" *)
		   output wire [3: 0] m_axi_arcache,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi ARPROT" *)
		   output wire [2: 0] m_axi_arprot,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi ARQOS" *)
		   output wire [3: 0] m_axi_arqos,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi ARVALID" *)
		   output wire m_axi_arvalid,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi ARREADY" *)
		   input wire m_axi_arready,

		   //Read data channel.
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi RDATA" *)
		   input wire [(C_M_AXI_DATA_WIDTH - 1): 0] m_axi_rdata,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi RRESP" *)
		   input wire [1: 0] m_axi_rresp,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi RLAST" *)
		   input wire m_axi_rlast,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi RVALID" *)
		   input wire m_axi_rvalid,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 m_axi RREADY" *)
		   output wire m_axi_rready,

		   /***********************************************************************/
		   //Master JTAG interface
		   /***********************************************************************/
		   //Global ACLK
		   (* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 m_jtag_aclk CLK" *)
		   (* X_INTERFACE_PARAMETER = "ASSOCIATED_BUSIF m_jtag, ASSOCIATED_RESET m_jtag_aresetn" *)
		   input wire m_jtag_aclk,

		   //Global ARESETn
		   (* X_INTERFACE_INFO = "xilinx.com:signal:reset:1.0 m_jtag_aresetn RST" *)
		   (* X_INTERFACE_PARAMETER = "POLARITY ACTIVE_LOW" *)
		   input wire m_jtag_aresetn,

		   (* X_INTERFACE_INFO = "xilinx.com:interface:jtag:2.0 m_jtag TCK" *)
		   output wire m_tck,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:jtag:2.0 m_jtag TMS" *)
		   output wire m_tms,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:jtag:2.0 m_jtag TDI" *)
		   output wire m_tdi,
		   (* X_INTERFACE_INFO = "xilinx.com:interface:jtag:2.0 m_jtag TDO" *)
		   input wire m_tdo,

		   (* X_INTERFACE_INFO = "CSIC.com.cn:user:jtag:1.0 m_jtag_io TCK_IO" *)
		   inout wire m_tck_io,
		   (* X_INTERFACE_INFO = "CSIC.com.cn:user:jtag:1.0 m_jtag_io TCK_T" *)
		   output wire m_tck_t,
		   (* X_INTERFACE_INFO = "CSIC.com.cn:user:jtag:1.0 m_jtag_io TMS_IO" *)
		   inout wire m_tms_io,
		   (* X_INTERFACE_INFO = "CSIC.com.cn:user:jtag:1.0 m_jtag_io TMS_T" *)
		   output wire m_tms_t,
		   (* X_INTERFACE_INFO = "CSIC.com.cn:user:jtag:1.0 m_jtag_io TDI_IO" *)
		   inout wire m_tdi_io,
		   (* X_INTERFACE_INFO = "CSIC.com.cn:user:jtag:1.0 m_jtag_io TDI_T" *)
		   output wire m_tdi_t,
		   (* X_INTERFACE_INFO = "CSIC.com.cn:user:jtag:1.0 m_jtag_io TDO_IO" *)
		   inout wire m_tdo_io,
		   (* X_INTERFACE_INFO = "CSIC.com.cn:user:jtag:1.0 m_jtag_io TDO_T" *)
		   output wire m_tdo_t,
		   
		   (* X_INTERFACE_INFO = "xilinx.com:signal:interrupt:1.0 intr INTERRUPT" *)
		   (* X_INTERFACE_PARAMETER = "SENSITIVITY LEVEL_HIGH" *)
		   output wire intr
	   );

wire ENABLE;
wire BUSY;
wire [31: 0] LENGTH;
wire [31: 0] FREQ_WORD;
wire [31: 0] TMS_MEM_ADDR;
wire [31: 0] TDI_MEM_ADDR;
wire [31: 0] TDO_MEM_ADDR;

template_s_axi_lite
	#
	(
		.C_AXI_ADDR_WIDTH(C_S_AXI_ADDR_WIDTH),
		.C_AXI_DATA_WIDTH(C_S_AXI_DATA_WIDTH)
	)
	s_axi_lite_inst
	(
		.ENABLE(ENABLE),
		.BUSY(BUSY),
		.LENGTH(LENGTH),
		.FREQ_WORD(FREQ_WORD),
		.TMS_MEM_ADDR(TMS_MEM_ADDR),
		.TDI_MEM_ADDR(TDI_MEM_ADDR),
		.TDO_MEM_ADDR(TDO_MEM_ADDR),
		
		.intr(intr),

		.s_axi_lite_aclk(s_axi_lite_aclk),
		.s_axi_lite_aresetn(s_axi_lite_aresetn),
		//Write address channel. AWVALID, AWREADY, AWADDR, AWPROT
		.s_axi_lite_awvalid(s_axi_lite_awvalid),
		.s_axi_lite_awready(s_axi_lite_awready),
		.s_axi_lite_awaddr(s_axi_lite_awaddr),
		.s_axi_lite_awprot(s_axi_lite_awprot),
		//Write data channel. WVALID, WREADY, WDATA, WSTRB
		.s_axi_lite_wvalid(s_axi_lite_wvalid),
		.s_axi_lite_wready(s_axi_lite_wready),
		.s_axi_lite_wdata(s_axi_lite_wdata),
		.s_axi_lite_wstrb(s_axi_lite_wstrb),
		//Write response channel. BVALID, BREADY, BRESP
		.s_axi_lite_bvalid(s_axi_lite_bvalid),
		.s_axi_lite_bready(s_axi_lite_bready),
		.s_axi_lite_bresp(s_axi_lite_bresp),
		//Read address channel. ARVALID, ARREADY, ARADDR, ARPROT
		.s_axi_lite_arvalid(s_axi_lite_arvalid),
		.s_axi_lite_arready(s_axi_lite_arready),
		.s_axi_lite_araddr(s_axi_lite_araddr),
		.s_axi_lite_arprot(s_axi_lite_arprot),
		//Read data channel. RVALID, RREADY, RDATA, RRESP
		.s_axi_lite_rvalid(s_axi_lite_rvalid),
		.s_axi_lite_rready(s_axi_lite_rready),
		.s_axi_lite_rdata(s_axi_lite_rdata),
		.s_axi_lite_rresp(s_axi_lite_rresp)
	);

jtag_lm_process
	#(
		.C_JTAG_TYPE(C_JTAG_TYPE),
		.C_JTAG_TRI_POLARITY(C_JTAG_TRI_POLARITY),
		.C_VECTOR_LEN(C_VECTOR_LEN),

		.C_AXI_MAX_BURST_LENGTH(C_M_AXI_MAX_BURST_LENGTH),
		.C_AXI_ADDR_WIDTH(C_M_AXI_ADDR_WIDTH),
		.C_AXI_DATA_WIDTH(C_M_AXI_DATA_WIDTH)
	)
	jtag_lm_process_inst
	(
		.m_jtag_aclk(m_jtag_aclk),
		.m_jtag_aresetn(m_jtag_aresetn),

		.ENABLE(ENABLE),
		.BUSY(BUSY),
		.LENGTH(LENGTH),
		.FREQ_WORD(FREQ_WORD),
		.TMS_MEM_ADDR(TMS_MEM_ADDR),
		.TDI_MEM_ADDR(TDI_MEM_ADDR),
		.TDO_MEM_ADDR(TDO_MEM_ADDR),

		.m_tck(m_tck),
		.m_tms(m_tms),
		.m_tdi(m_tdi),
		.m_tdo(m_tdo),

		.m_tck_io(m_tck_io),
		.m_tms_io(m_tms_io),
		.m_tdi_io(m_tdi_io),
		.m_tdo_io(m_tdo_io),

		.m_tck_t(m_tck_t),
		.m_tms_t(m_tms_t),
		.m_tdi_t(m_tdi_t),
		.m_tdo_t(m_tdo_t),

		.m_axi_aclk(m_axi_aclk),
		.m_axi_aresetn(m_axi_aresetn),

		.m_axi_awaddr(m_axi_awaddr),
		.m_axi_awlen(m_axi_awlen),
		.m_axi_awsize(m_axi_awsize),
		.m_axi_awburst(m_axi_awburst),
		.m_axi_awlock(m_axi_awlock),
		.m_axi_awcache(m_axi_awcache),
		.m_axi_awprot(m_axi_awprot),
		.m_axi_awqos(m_axi_awqos),
		.m_axi_awvalid(m_axi_awvalid),
		.m_axi_awready(m_axi_awready),
		.m_axi_wdata(m_axi_wdata),
		.m_axi_wstrb(m_axi_wstrb),
		.m_axi_wlast(m_axi_wlast),
		.m_axi_wvalid(m_axi_wvalid),
		.m_axi_wready(m_axi_wready),
		.m_axi_bresp(m_axi_bresp),
		.m_axi_bvalid(m_axi_bvalid),
		.m_axi_bready(m_axi_bready),
		.m_axi_araddr(m_axi_araddr),
		.m_axi_arlen(m_axi_arlen),
		.m_axi_arsize(m_axi_arsize),
		.m_axi_arburst(m_axi_arburst),
		.m_axi_arlock(m_axi_arlock),
		.m_axi_arcache(m_axi_arcache),
		.m_axi_arprot(m_axi_arprot),
		.m_axi_arqos(m_axi_arqos),
		.m_axi_arvalid(m_axi_arvalid),
		.m_axi_arready(m_axi_arready),
		.m_axi_rdata(m_axi_rdata),
		.m_axi_rresp(m_axi_rresp),
		.m_axi_rlast(m_axi_rlast),
		.m_axi_rvalid(m_axi_rvalid),
		.m_axi_rready(m_axi_rready)
	);


endmodule